#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<unistd.h>
#include<netinet/in.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>


int main(int argc,char* argv[]){
    if(argc<=2){
        printf("Usage:%s ip_address portname\n",argv[0]);
        return 0;
    }

    //获得ip和端口
    const char* ip=argv[1];
    int port=atoi(argv[2]);

    //定义套接字
    int listenfd=socket(PF_INET,SOCK_STREAM,0);
    assert(listenfd>=1);

    //定义服务端的信息，主要是协议族，端口号和ip
    struct sockaddr_in address;
    memset(&address,0,sizeof(address));
    address.sin_family=AF_INET;
    address.sin_port=htons(port);
    inet_pton(AF_INET,ip,&address.sin_addr);

    //将套接字和服务端绑定
    int ret=0;
    ret=bind(listenfd,(struct sockaddr*)(&address),sizeof(address));
    assert(ret!=-1);

    //接收信号
    ret=listen(listenfd,5);
    assert(ret!=-1);


    //客户端
    struct sockaddr_in client;
    socklen_t client_addrlength=sizeof(client);
    int sockfd=accept(listenfd,(struct sockaddr*)(&client),&client_addrlength);
    /*
    注意，这里的sockfd是服务端accept后又新创建的套接字，以便原来的listenfd套接字继续执行接听客
    户端的任务。(这个sockfd就相当于服务端与客户端之间的接口，理解成客户端的套接字好像也没问题)
    */


    //缓冲区及接收信息
    char buf_size[1024]={0};
    int recv_size=0;
    recv_size=recv(sockfd,buf_size,sizeof(buf_size),0);

    //服务端把消息发送回客户端
    int send_size=0;
    send_size=send(sockfd,buf_size,recv_size,0);

    close(sockfd);
    close(listenfd);
    return 0;
}

/*
 可以先运行这一程序作为服务端，然后nc命令充当客户端，使用方式是./webserver.o 127.0.0.1 2024(2024是端口号，可以自己指定)
 效果就是客户端发送一条消息，服务端收到后发回去，相当于echo功能，但是因为只有一个recv(),一个send()，所以客户端发送一条消息
 后服务端就会发回消息直接关闭

 我发现这个服务端，如果打开，客户端不用，直接关闭，那么再打开是可以直接打开的。 但是如果客户端使用了再立刻打开，ret=listen(listenfd,
 5);assert(ret!=-1);就会assert断言。 可能是因为端口关闭需要时间？但理论上端口关闭是立即关闭的(而且netstatu查看端口状况端口确实没有
 占用)，这里原因没有深究。
 其次，这个listen(listenfd,5),意思是服务端队列中最多有5个客户排队请求，测试发现当大于5个连接的时候确实与服务器交互没反应，但是并不是
 连接不上，连接上了并且没有提示，服务器不应答，这样感觉还挺坑的吧
*/
